package org.dezenho.client.SO;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.rmi.Naming;
import java.rmi.RMISecurityManager;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

import org.dezenho.client.RMI.ClientFacade;
import org.dezenho.client.RN.Adivinhador;
import org.dezenho.client.RN.Desenhista;
import org.dezenho.client.RN.SalaEspera;
import org.dezenho.common.RMI.ServerInterface;

/**
 * Classe Responsavel pela conexao e por todas as chamadas remotas alem de
 * manter instancias das RNs, da classe controadora de telas
 * 
 * @author marcelasobrinhopereira
 * 
 */
public class DezenhoClient {

	private static DezenhoClient instance = new DezenhoClient();
	private DezenhoTelaClient dezenhoTelaClient;
	private Desenhista desenhista;
	private Adivinhador adivinhador;
	private SalaEspera salaEspera;
	private ServerInterface server;
	private String nome;

	/**
	 * Construtor
	 */
	private DezenhoClient() {
		setDezenhoTelaClient(new DezenhoTelaClient());
		setDesenhista(new Desenhista());
		setAdivinhador(new Adivinhador());
		setSalaEspera(new SalaEspera());
	}

	/**
	 * Metodo responsavel por chamar o inicio do cliente quandoa aplicacao e
	 * iniciada
	 * 
	 * @param args
	 */
	public static void main(String args[]) {
		getInstance().iniciaCliente();
	}

	/**
	 * Metodo repsonsavel por exibir tela inicial
	 */
	public void iniciaCliente() {
		getDezenhoTelaClient().apresentaTelaInicial();
	}

	/**
	 * Metodo responsavel por Finalizar Cliente e desconectar-se do servidor
	 */
	public void encerraCliente() {
		try {
			if(getServer() != null){
				getServer().desconectaUsuario(getIPUsuario());
				Registry r = LocateRegistry.getRegistry();
				r.unbind("dezenhoClient");
			}
			this.finalize();
			System.exit(0);
		}catch (Throwable e) {
			getDezenhoTelaClient().apresentaMensagem("Erro no encerramento do cliente");
			e.printStackTrace();
		}
	}

	/**
	 * Metodo responsavel por levantar o cliente no registro RMI e conectar-se
	 * ao servidor
	 * 
	 * @param nome
	 */
	public void conectaServidor(String nome) {

		// Cria a si como servidor para acessos do Server remoto
		try {
			setNome(nome);
		System.setSecurityManager(new RMISecurityManager());
		Registry r = LocateRegistry.getRegistry();
		r.bind("dezenhoClient", new ClientFacade());
		} catch (Exception e) {
			e.printStackTrace();
			getDezenhoTelaClient().apresentaMensagem("Erro no levantamento do cliente");
			
		}
		try{
			// Conecta ao servidor remoto
			setServer((ServerInterface) Naming.lookup("rmi://" + getIPServer() + "/dezenhoServer"));
			getServer().conectaUsuario(getIPUsuario(), getNome());
		} catch (Exception a) {
			a.printStackTrace();
			getDezenhoTelaClient().apresentaMensagem("Erro na conexao com o servidor");
			
		}

	}

	private String getIPServer() {
		try {
			BufferedReader reader =  new BufferedReader(
					new FileReader(System.getProperty("user.dir") + File.separator + "IPServer"));
			return reader.readLine();
		} catch (Exception e) {
			getDezenhoTelaClient().apresentaMensagem("Nao foi possivel obter o IP do servidor");
			e.printStackTrace();
		}
		return null;		
	}
	
	public String getIPUsuario() {
		try {
			BufferedReader reader =  new BufferedReader(
					new FileReader(System.getProperty("user.dir") + File.separator + "IPClient"));
			return reader.readLine();
		} catch (Exception e) {
			getDezenhoTelaClient().apresentaMensagem("Nao foi possivel obter o IP do cliente");
			e.printStackTrace();
		}
		return null;	
	}
	
	//Metodos de acesso

	public ServerInterface getServer() {
		return server;
	}

	protected void setServer(ServerInterface server) {
		this.server = server;
	}

	public static DezenhoClient getInstance() {
		return instance;
	}
	
	public String getNome() {
		return nome;
	}

	public void setNome(String nome) {
		this.nome = nome;
	}

	public DezenhoTelaClient getDezenhoTelaClient() {
		return dezenhoTelaClient;
	}

	protected void setDezenhoTelaClient(DezenhoTelaClient dezenhoTelaClient) {
		this.dezenhoTelaClient = dezenhoTelaClient;
	}

	public Desenhista getDesenhista() {
		return desenhista;
	}

	protected void setDesenhista(Desenhista desenhista) {
		this.desenhista = desenhista;
	}

	public Adivinhador getAdivinhador() {
		return adivinhador;
	}

	protected void setAdivinhador(Adivinhador adivinhador) {
		this.adivinhador = adivinhador;
	}

	public SalaEspera getSalaEspera() {
		return salaEspera;
	}

	protected void setSalaEspera(SalaEspera salaEspera) {
		this.salaEspera = salaEspera;
	}

}
